package me.august.lumen.compile; import joptsimple.OptionParser; import joptsimple.OptionSet; import joptsimple.OptionSpec; import me.august.lumen.common.FileUtil; import me.august.lumen.compile.parser.ast.ProgramNode; import me.august.lumen.compile.resolve.lookup.DependencyManager; import me.august.lumen.compile.resolve.lookup.JarLookup; import me.august.lumen.compile.scanner.TokenSource; import org.fusesource.jansi.Ansi; import java.io.File; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; import java.util.Collection; import java.util.jar.JarFile; public class CompileCommandLine implements Runnable { private String[] args; private Collection<String> keywordsToIgnore; private DependencyManager deps = new DependencyManager(); public CompileCommandLine(String[] args) { this.args = args; } @Override public void run() { OptionParser parser = new OptionParser(); OptionSpec<String> ignore = parser.accepts("ignore").withRequiredArg().describedAs("Keywords for the lexer to ignore"); OptionSpec<String> dependency = parser.accepts("dependency").withRequiredArg().describedAs("Jar files to use as dependencies"); OptionSet options = parser.parse(args); keywordsToIgnore = options.valuesOf(ignore); for (String depFile : options.valuesOf(dependency)) { try { deps.addSource(new JarLookup(new JarFile(depFile))); } catch (IOException e) { throw new RuntimeException("Jar file dependency not found: " + depFile); } } for (Object f : options.nonOptionArguments()) { if (f instanceof String) { String file = new File((String) f).getAbsolutePath(); String source = FileUtil.read(file); if (source == null) throw new RuntimeException("File not found: " + file); compileSource(source, file); } } } private void compileSource(String src, String file) { Driver driver = new Driver(src, deps); TokenSource lexer = driver.phase1Scanning(keywordsToIgnore); ProgramNode program = driver.phase2Parsing(lexer); driver.phase3Resolving(program); driver.phase4Analysis(program); String name = program.getClassNode().getName(); saveBytecode(driver.phase5Bytecode(program), name, file); Ansi ansi = Ansi.ansi() .a(Ansi.Attribute.INTENSITY_BOLD).fg(Ansi.Color.GREEN) .a("Successfully compiled " + file) .reset(); System.out.println(ansi); } private void saveBytecode(byte[] bytes, String name, String path) { String fileName = new File(path).getParentFile() + "/" + name + ".class"; try { Files.write(Paths.get(fileName), bytes); } catch (IOException e) { throw new RuntimeException(e); } } }